package com.sinodata.bsm.center.message;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.jms.JMSException;

import org.apache.log4j.Logger;

import com.sinodata.bsm.center.bean.ResBean;
import com.sinodata.bsm.center.cache.ProbeCache;
import com.sinodata.bsm.center.cache.ResCache;
import com.sinodata.bsm.center.util.spring.SpringContextHolder;
import com.sinodata.bsm.common.constants.SystemStatus;
import com.sinodata.bsm.common.message.ServiceMessage;
import com.sinodata.bsm.common.vo.Attribute;
import com.sinodata.bsm.common.vo.CollectField;
import com.sinodata.bsm.common.vo.CollectParam;
import com.sinodata.bsm.common.vo.CollectSchedule;
import com.sinodata.bsm.common.vo.CollectTask;
import com.sinodata.bsm.common.vo.Probe;
import com.sinodata.bsm.common.vo.Property;
import com.sinodata.bsm.common.vo.ProtocolParameter;
import com.sinodata.bsm.common.vo.Res;
import com.sinodata.bsm.common.vo.ResAttrVal;
import com.sinodata.bsm.common.vo.ResRelation;

/**
 * <p>
 * Description:
 * </p>
 * 
 * @author tangli
 * @version 1.0
 * 
 * <p>
 * History:
 * 
 * Date Author Version Description
 * ---------------------------------------------------------------------------------
 * 2012-6-12 下午2:32:07 tangli 1.0 To create
 * </p>
 * 
 * @since
 * @see
 */

public class ProbeMessenger {
    private static final Logger logger = Logger.getLogger(ProbeMessenger.class);
    private static ProbeCache probeCache = SpringContextHolder.getBean(ProbeCache.class);
    private static ResCache resCache = SpringContextHolder.getBean(ResCache.class);

    private ProbeMessenger() {
    }

    /**
     * 通知agent一个service请求。
     * 
     * @param agentId
     * @param request
     */
    public static void notify(Long probeId, ServiceMessage msg) {
        Probe probe = probeCache.get(probeId.longValue());
        try {
            if (probe != null && probe.getStatus().intValue() == SystemStatus.STATUS_RUN) {
                Messenger.getInstance().sendAsynMessage(probeId, msg);
            }
        } catch (JMSException e) {
            logger.error("[FAILED] NOTIFY " + probeId + "\t" + msg.toString());
        }
    }

    private static void notify(Long probeId, String serName, String method, Object... params) {
        Probe probe = probeCache.get(probeId);
        if (probe != null && probe.getStatus().equals(SystemStatus.STATUS_RUN)) {
            ServiceMessage msg = new ServiceMessage();
            msg.setSrvId(serName);
            msg.setMethod(method);
            msg.setParams(params);
            notify(probeId, msg);
        }
    }

    public static void notifyResAdd(Res res, List<ResAttrVal> attValList, ResRelation resRelation) {
        ServiceMessage msg = new ServiceMessage();
        msg.setSrvId("ResService");
        msg.setMethod("addRes");
        if (resRelation == null) {
            resRelation = new ResRelation();
        }
        Object[] args = { res, attValList, resRelation };
        msg.setParams(args);
        notify(res.getProbeId(), msg);
    }

    public static void notifyBatchResUpdate(Long probeId, List<Object[]> resList) {
        ServiceMessage msg = new ServiceMessage();
        msg.setSrvId("ResService");
        msg.setMethod("batchUpdateRes");
        Object[] args = { resList };
        msg.setParams(args);
        notify(probeId, msg);
    }

    public static void notifyResUpdate(Res res, List<ResAttrVal> attValList, ResRelation resRelation) {
        ServiceMessage msg = new ServiceMessage();
        msg.setSrvId("ResService");
        msg.setMethod("updateRes");
        if (resRelation == null) {
            resRelation = new ResRelation();
        }
        Object[] args = { res, attValList, resRelation };
        msg.setParams(args);
        notify(res.getProbeId(), msg);
    }

    public static void notifyResDelete(Res res) {
        ServiceMessage msg = new ServiceMessage();
        msg.setSrvId("ResService");
        msg.setMethod("deleteRes");
        Object[] args = { res.getId() };
        msg.setParams(args);
        notify(res.getProbeId(), msg);
    }

    /**
     * 资源暂停
     * 
     * @param res
     */
    public static void notifyResPaused(Res res) {
        ServiceMessage msg = new ServiceMessage();
        msg.setSrvId("ResService");
        msg.setMethod("setResPaused");
        Object[] args = { res.getId() };
        msg.setParams(args);
        notify(res.getProbeId(), msg);
    }

    /**
     * 恢复监控
     * 
     * @param res
     */
    public static void notifyResResume(Res res) {
        ServiceMessage msg = new ServiceMessage();
        msg.setSrvId("ResService");
        msg.setMethod("resumeResPaused");
        Object[] args = { res.getId() };
        msg.setParams(args);
        notify(res.getProbeId(), msg);
    }

    // 采集规则启动或暂停
    public static void notifyCollectTaskPausedOrNormal(CollectTask task) throws Exception {
        ServiceMessage msg = new ServiceMessage();
        msg.setSrvId("CollectorService");
        msg.setMethod("setCollectTaskPausedOrNormal");
        Object[] args = { task.getId(), task.getStatus() };
        msg.setParams(args);
        Long probeId = resCache.get(task.getResId().longValue()).getProbeId();
        notify(probeId, msg);
    }

    public static void notifyCollectAddOrUpdate(CollectTask task, List<CollectSchedule> scheduleList, List<CollectParam> paramList, List<CollectField> fieldList) throws Exception {
        ServiceMessage msg = new ServiceMessage();
        msg.setSrvId("CollectorService");
        msg.setMethod("addCollectTask");
        Object[] args = { task, scheduleList, paramList, fieldList };
        msg.setParams(args);
        Long probeId = resCache.get(task.getResId().longValue()).getProbeId();
        notify(probeId, msg);
    }

    public static void notifyCollectDelete(Long resId, Long taskId) {
        ServiceMessage msg = new ServiceMessage();
        msg.setSrvId("CollectorService");
        msg.setMethod("deleteCollectTask");
        Object[] args = { taskId };
        msg.setParams(args);
        Long probeId = resCache.get(resId.longValue()).getProbeId();
        notify(probeId, msg);
    }

    public static void notifyPropertyAdd(Property property) {
        ServiceMessage msg = new ServiceMessage();
        msg.setSrvId("PropertyService");
        msg.setMethod("addResProperty");
        Object[] args = { property };
        msg.setParams(args);
        Long probeId = resCache.get(property.getResId().longValue()).getProbeId();
        notify(probeId, msg);
    }

    public static void notifyAttributeAdd(Attribute attribute) {
        ServiceMessage msg = new ServiceMessage();
        msg.setSrvId("PropertyService");
        msg.setMethod("addResAttribute");
        Object[] args = { attribute };
        msg.setParams(args);
        Long probeId = resCache.get(attribute.getResId().longValue()).getProbeId();
        notify(probeId, msg);
    }

    //
    public static void notifyCollect(Long[] resIds) {
        // 为批处理做准备，把res按agentId分类，放入Map中。
        Map<Long, List> probeMap = new HashMap<Long, List>();
        for (int i = 0; i < resIds.length; i++) {
            Long probeId = resCache.get(resIds[i]).getProbeId();
            List resList = probeMap.get(probeId);
            if (resList != null) {
                resList.add(resIds[i]);
            } else {
                List newList = new ArrayList();
                newList.add(resIds[i]);
                probeMap.put(probeId, newList);
            }
        }

        for (Iterator iter = probeMap.entrySet().iterator(); iter.hasNext();) {
            Entry element = (Entry) iter.next();
            Long probeId = (Long) element.getKey();
            List list = (List) element.getValue();
            try {
                notify(probeId, "CollectorService", "collect", list);
            } catch (Exception e) {
                logger.error("failed to call notifyCollect... ", e);
            }
        }
    }

    /**
     * 通知连接协议变更
     * 
     * @param changed
     *            --A 新增 --R 删除 --U 修改
     * @param obj
     *            删除时保证ID有值
     */
    public static void notifyProtocolParameterChanged(String changed, ProtocolParameter obj) {
        ServiceMessage msg = new ServiceMessage();
        msg.setSrvId("ProtocalParameterService");
        msg.setMethod("changedProtocol");
        Object[] args = { changed, obj };
        msg.setParams(args);
        List<Probe> probes = probeCache.getAll();
        for (Probe probe : probes) {
            // if (probe.getStatus().intValue() == SystemStatus.STATUS_RUN) {
            notify(probe.getId(), msg);
            // }
        }
    }
}
